/**
 * Copyright (c) Tapas Mobile.  All Rights Reserved.
 *
 * @author DaiHui
 * @version 1.0
 */

package com.dotools.utils;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import androidx.core.content.FileProvider;

public class PackageUtils {
    static int sMyVersionCode = -1;
    static String sMyversionName = null;
    static PackageManager sPackageManager = null;
    static String sSelfBuildTime = null;
    public static final int APP_INSTALL_REQUEST = 888;

    public static boolean isAppInstalled(Context context, String pkgName) {
        PackageInfo packageInfo;
        try {
            packageInfo = context.getPackageManager().getPackageInfo(pkgName, 0);
        } catch (NameNotFoundException e) {
            packageInfo = null;
            // e.printStackTrace();
        }
        if (packageInfo == null) {
            return false;
        } else {
            return true;
        }
    }

    private static void ensureService() {
        if (sPackageManager == null) {
            sPackageManager = Utilities.getApplicationContext().getPackageManager();
        }
    }

    private static void getMyversion() {
        if (sMyVersionCode < 0 || sMyversionName == null) {
            ensureService();

            try {
                PackageInfo info = sPackageManager.getPackageInfo(getPackageName(),
                        PackageManager.GET_UNINSTALLED_PACKAGES);
                sMyversionName = info.versionName;
                sMyVersionCode = info.versionCode;
            } catch (Exception e) {
            }
        }
    }

    public static String getPackageName() {
        return Utilities.getApplicationContext().getPackageName();
    }

    public static String getVersionName(Context context, String pkgName) {
        PackageManager pm = context.getPackageManager();
        try {
            PackageInfo pi = pm.getPackageInfo(pkgName, 0);
            return pi.versionName;
        } catch (Exception e) {
            return "";
        }
    }

    public static int getVersionCode(Context context) {
        try {
            PackageInfo pi = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return pi.versionCode;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static int getVersionCode(Context cxt, String pkgName, int defValue) {
        try {
            PackageManager pm = cxt.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(pkgName, 0);
            return pi.versionCode;
        } catch (Exception e) {
            // ignore
        }
        return defValue;
    }

    public static String guessBuildTime() {
        if (sSelfBuildTime == null) {
            sSelfBuildTime = TimeUtils.getTimeString(guessBuildTime(getPackageName()));
        }
        return sSelfBuildTime;
    }

    public static long guessBuildTime(String pkgName) {
        ensureService();

        try {
            ApplicationInfo ai = sPackageManager.getApplicationInfo(pkgName, 0);
            ZipFile zf = new ZipFile(ai.sourceDir);
            ZipEntry ze = zf.getEntry("classes.dex");
            return ze.getTime();
        } catch (Exception e) {
        }

        return -1;
    }

    public static boolean isLegacyDevice() {
        return Build.VERSION_CODES.GINGERBREAD_MR1 >= Build.VERSION.SDK_INT;
    }

    public static boolean installPackage(Context context, String path) {
        return installPackage(context, path, null);
    }

    public static boolean installPackage(Context context, String path, String installerPackage) {
        try {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            File file = new File(path);
            if (!file.exists())
                return false;
            Uri apkUri = null;
            if (Build.VERSION.SDK_INT >= 24) {
                apkUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            } else {
                apkUri = Uri.fromFile(file);

            }
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            if (installerPackage != null) {
                intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackage);
            }
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public static boolean isPkgInstalled(Context context, String packageName) {
        if (packageName == null || "".equals(packageName))
            return false;
        android.content.pm.ApplicationInfo info = null;
        try {
            info = context.getPackageManager().getApplicationInfo(packageName, 0);
            return info != null;
        } catch (NameNotFoundException e) {
            return false;
        }
    }

    public static boolean isActivityInstalled(Context context, String packageName, String className) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(packageName, className));
        List<ResolveInfo> activitys = context.getPackageManager().queryIntentActivities(intent, PackageManager.GET_META_DATA);
        return activitys.size() > 0;
    }

    public static boolean isReceiverInstalled(Context context, String packageName, String className) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(packageName, className));
        List<ResolveInfo> broadcastReceivers = context.getPackageManager().queryBroadcastReceivers(intent, PackageManager.GET_META_DATA);
        return broadcastReceivers.size() > 0;
    }

    public static boolean isPkgInstalledByAction(Context context, String pkgName,
                                                 String action) {
        try {
            Intent intent = new Intent(action);
            if (pkgName != null) {
                intent.setPackage(pkgName);
            }
            List<ResolveInfo> apps = context.getPackageManager().queryIntentActivities(intent, 0);
            return apps != null && apps.size() > 0;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isPkgInstalledByIntent(Context context,
                                                 Intent intent) {
        try {
            List<ResolveInfo> apps = context.getPackageManager().queryIntentActivities(intent, 0);
            return apps != null && apps.size() > 0;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isSystemPkg(Context context, String pkg) {
        if (pkg == null || "".equals(pkg)) {
            return false;
        }
        android.content.pm.ApplicationInfo info = null;
        try {
            info = context.getPackageManager().getApplicationInfo(pkg, 0);
            if (info != null) {
                List<PackageInfo> apps = context.getPackageManager().getInstalledPackages(0);
                for (PackageInfo p : apps) {
                    if (p.packageName.equals(pkg)) {
                        if ((p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) {
                        }
                    }
                }
                return apps != null && apps.size() > 0;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    public static void installAppFroResult(Activity activity, String path) throws Exception {
        File file = new File(path);
        if(file.exists()){
            Uri apkUri = null;
            if(Build.VERSION.SDK_INT >= 24){
                apkUri = FileProvider.getUriForFile(activity,activity.getPackageName()+".fileprovider",file);
            }else {
                apkUri = Uri.fromFile(file);
            }
            Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
            intent.setData(apkUri);
            intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
            intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            activity.startActivityForResult(intent, APP_INSTALL_REQUEST);
        }
    }

    public static void installApp(Context context, String path) throws Exception {
        File file = new File(path);
        if(file.exists()){
            Uri apkUri = null;
            if(Build.VERSION.SDK_INT >= 24){
                apkUri = FileProvider.getUriForFile(context,context.getPackageName()+".fileprovider",file);
            }else {
                apkUri = Uri.fromFile(file);
            }
            if(apkUri==null) return;
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_VIEW);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            context.startActivity(intent);
        }
    }

    public static boolean checkApkValidity(Context context, String apkPath) {
        try {
            PackageManager packageManager = context.getPackageManager();
            if (packageManager != null) {
                PackageInfo packageArchiveInfo = packageManager.getPackageArchiveInfo(apkPath, 0);
                if (packageArchiveInfo != null)
                    return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /****
     * 获取用户手机手动安装的所有程序包名集合
     * @param mContext
     * @return
     */
    public static List<String> getAllInstallAppPackageName(Context mContext) {
        List<String> packageNameList = null;
        try {
            final PackageManager packageManager = mContext.getPackageManager();  //获取packagemanager
            List<PackageInfo> pinfo = packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);  //获取所有已安装程序的包信息
            if (pinfo != null && !pinfo.isEmpty()) {
                packageNameList = new ArrayList<String>();
                for (PackageInfo info : pinfo) {
                    /**该值大于0时，表示获取的应用为系统预装的应用，反之则为手动安装的应用*/
                    if ((info.applicationInfo.flags & info.applicationInfo.FLAG_SYSTEM) <= 0) {
                        packageNameList.add(info.packageName);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return packageNameList;
    }

    public static void installAppAndRunAfterInstall(Context context, String path) {
        installAppAndRunAfterInstall(context, path, -1);
    }

    public static void installAppAndRunAfterInstall(Context context, String path, int type) {
        String packageName = getArchivePackageName(context, path);
        if (packageName != null) {
            LauncherAfterInstalled.getInstance(context).monitor(packageName);
        }
        try {
            installApp(context, path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getArchivePackageName(Context context, String apkPath) {
        try {
            PackageInfo pi = context.getPackageManager().getPackageArchiveInfo(apkPath, 0);
            ApplicationInfo applicationInfo = pi.applicationInfo;
            applicationInfo.sourceDir = apkPath;
            applicationInfo.dataDir = apkPath;
            return applicationInfo.packageName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得应用入口intent
     */
    public static Intent getLaunchIntent(Context context) {
        PackageManager pm = context.getPackageManager();
        return pm.getLaunchIntentForPackage(context.getPackageName());
    }

    /**
     * 获取配置信息：分发渠道ID
     */
    public static String getUmengChannel(Context ctx) {
        ApplicationInfo appInfo = null;
        try {
            appInfo = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);
            Object obj = appInfo.metaData.get("UMENG_CHANNEL");
            if (obj instanceof Integer) {
                return appInfo.metaData.getInt("UMENG_CHANNEL") + "";
            } else if (obj instanceof String) {
                return appInfo.metaData.getString("UMENG_CHANNEL");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /*
     * 获取程序 图标
     */
    public static Bitmap getAppIcon(Context context, String packname) {
        try {
            PackageManager pm = context.getPackageManager();
            ApplicationInfo info = pm.getApplicationInfo(packname, 0);
            Drawable d = info.loadIcon(pm);
            return ((BitmapDrawable) d).getBitmap();
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void startupApp(Context context, String pkgName) {
        try {
            Intent intent = context.getPackageManager().getLaunchIntentForPackage(pkgName);
            if (intent != null) {
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                context.startActivity(intent);
            }
        } catch (Exception e) {
//            LogHelper.w(TAG, "Failed to startup the app: " + pkgName, e);
        }
    }

    /***
     * 获取当前设备是否属于五大厂商手机名称
     * @return
     */
    public static String getDeviceChannel() {
        if (DevicesUtils_HuaWei.isHuaWeiRom()) {
            return "huawei";
        } else if (DevicesUtils_Oppo.isOppoDevice()) {
            return "oppo";
        } else if (DevicesUtils_Vivo.isVivoDevice()) {
            return "bubugao";
        } else if (DevicesUtils_MIUI.isMIUI()) {
            return "xiaomi";
        } else if (DevicesUtils_MeiZu.isMeizuDevice()) {
            return "meizu";
        } else {
            return "other";
        }
    }

    /**
     * 获取应用程序名称
     */
    public static String getAppName(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            int labelRes = packageInfo.applicationInfo.labelRes;
            return context.getResources().getString(labelRes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

